import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import type { LoginPayload, RefreshPayload } from '@/api/auth'
import { login as loginApi, refreshToken as refreshApi } from '@/api/auth'
import type { TokenResponse } from '@/types/api'

interface AuthState {
  accessToken: string | null
  refreshToken: string | null
  tenantId: string | null
  username: string | null
  expiresAt: number | null
  refreshExpiresAt: number | null
}

const STORAGE_KEY = 'app.auth'

function loadState(): AuthState {
  if (typeof window === 'undefined') {
    return createEmptyState()
  }
  try {
    const stored = window.localStorage.getItem(STORAGE_KEY)
    if (!stored) {
      return createEmptyState()
    }
    const parsed = JSON.parse(stored) as AuthState
    return {
      accessToken: parsed.accessToken || null,
      refreshToken: parsed.refreshToken || null,
      tenantId: parsed.tenantId || null,
      username: parsed.username || null,
      expiresAt: parsed.expiresAt || null,
      refreshExpiresAt: parsed.refreshExpiresAt || null
    }
  } catch (error) {
    console.warn('读取登录态失败:', error)
    return createEmptyState()
  }
}

function createEmptyState(): AuthState {
  return {
    accessToken: null,
    refreshToken: null,
    tenantId: null,
    username: null,
    expiresAt: null,
    refreshExpiresAt: null
  }
}

function persist(state: AuthState) {
  if (typeof window === 'undefined') {
    return
  }
  window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
}

export const useAuthStore = defineStore('auth', () => {
  const state = ref<AuthState>(loadState())
  const loading = ref(false)

  const isAuthenticated = computed(() => Boolean(state.value.accessToken))
  const accessToken = computed(() => state.value.accessToken)
  const refreshToken = computed(() => state.value.refreshToken)
  const tenantId = computed(() => state.value.tenantId)
  const username = computed(() => state.value.username)

  const canRefresh = computed(() => {
    if (!state.value.refreshToken || !state.value.refreshExpiresAt) {
      return false
    }
    return state.value.refreshExpiresAt > Date.now()
  })

  async function login(payload: LoginPayload) {
    loading.value = true
    try {
      const result = await loginApi(payload)
      applyToken(payload.tenantId, payload.username, result)
      return result
    } finally {
      loading.value = false
    }
  }

  async function refreshSession() {
    if (!refreshToken.value) {
      throw new Error('刷新令牌不存在')
    }
    const payload: RefreshPayload = {
      refreshToken: refreshToken.value
    }
    const result = await refreshApi(payload)
    if (!state.value.tenantId || !state.value.username) {
      throw new Error('租户或用户名缺失')
    }
    applyToken(state.value.tenantId, state.value.username, result)
    return result
  }

  function applyToken(tenant: string, user: string, token: TokenResponse) {
    const nextState: AuthState = {
      accessToken: token.accessToken,
      refreshToken: token.refreshToken,
      tenantId: tenant,
      username: user,
      expiresAt: Date.now() + token.expiresIn * 1000,
      refreshExpiresAt: Date.now() + token.refreshExpiresIn * 1000
    }
    state.value = nextState
    persist(nextState)
  }

  function logout() {
    state.value = createEmptyState()
    if (typeof window !== 'undefined') {
      window.localStorage.removeItem(STORAGE_KEY)
    }
  }

  function getAccessToken() {
    return accessToken.value
  }

  function getRefreshToken() {
    return refreshToken.value
  }

  function getTenantId() {
    return tenantId.value
  }

  return {
    loading,
    isAuthenticated,
    accessToken,
    refreshToken,
    tenantId,
    username,
    canRefresh,
    login,
    refreshSession,
    logout,
    getAccessToken,
    getRefreshToken,
    getTenantId
  }
})
